package com.example.administrator.testproject.flagTextview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.DrawableRes;
import android.support.annotation.Nullable;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.text.style.ImageSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.ViewTreeObserver;

import com.example.administrator.testproject.R;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by shengfh on 2018/1/18.
 */

public class TagTextView extends android.support.v7.widget.AppCompatTextView {

    private Builder builder;

    public static class TagType {
        static int TYPE_FLAG = 0;//标签
        static int TYPE_DRAWABLE = 1;//图片
        static int TYPE_TEXT_COLOR = 2;//带颜色字体
    }

    private int availableTextWidth;
    private int maxLine;
    private int paddingLeft;
    private int paddingRight;
    private int bufferWidth;
    private int width;
    private TextPaint paint;

    private float textSize;
    private float flagTextSize;
    private int textColor;
    private int flagTextColor;
    private float flagPadding;//flag左右padding
    private float flagMargin;//flag间距
    private float textMarginLeft;
    private float textMarginRight;
    private float lineSpacing;
    private float leftTotalWidth;
    private float rightTotalWidth;

    public TagTextView(Context context) {
        super(context);
    }

    public TagTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initView(attrs);
    }

    public TagTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(attrs);
    }


    private void initView(@Nullable AttributeSet attrs) {
        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.FlagTextView);
        textSize = typedArray.getDimension(R.styleable.FlagTextView_text_Size, 14);
        textColor = typedArray.getColor(R.styleable.FlagTextView_text_Color, getResources().getColor(R.color.gray_3));
        flagTextSize = typedArray.getDimension(R.styleable.FlagTextView_flag_textSize, 10);
        flagTextColor = typedArray.getColor(R.styleable.FlagTextView_flag_textColor, getResources().getColor(R.color.gray_3));
        flagPadding = typedArray.getDimension(R.styleable.FlagTextView_flag_padding, 5);
        flagMargin = typedArray.getDimension(R.styleable.FlagTextView_flag_margin, 5);
        textMarginLeft = typedArray.getDimension(R.styleable.FlagTextView_text_margin_left, 10);
        textMarginRight = typedArray.getDimension(R.styleable.FlagTextView_text_margin_right, 10);
        lineSpacing = typedArray.getDimension(R.styleable.FlagTextView_line_spacing, 5);
        maxLine = typedArray.getInt(R.styleable.FlagTextView_flag_max_line, 0);
        typedArray.recycle();

        paint = getPaint();
        getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

            @Override
            public void onGlobalLayout() {
                if (availableTextWidth == 0 && getWidth() > 0) {
                    width = getWidth();
                    paddingLeft = getPaddingLeft();
                    paddingRight = getPaddingRight();
                    paint.setTextSize(textSize);
                    draw();
                    if (Build.VERSION.SDK_INT >= 16) {
                        getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    } else {
                        getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    }
                }
            }
        });
    }

    public void draw() {
        if (builder == null) return;
        bufferWidth = (int) paint.getTextSize() * (builder.rightFlags.size());//缓冲区长度，空出两个字符的长度来给最后的省略号及图片

//        Log.e("Tag", builder.contentString + "availableTextWidth" + availableTextWidth);
        if (TextUtils.isEmpty(builder.contentString))
            return;
        StringBuffer flagBuffer = new StringBuffer();
        for (int i = 0; i < builder.leftFlags.size(); i++) {
            flagBuffer.append(builder.leftFlags.get(i).getTxt());
            flagBuffer.append(" ");
        }
        // 根据长度截取出剪裁后的文字
        builder.contentString = flagBuffer + builder.contentString;
        paint.setTextSize(textSize);
        String ellipsizeStr = builder.contentString;
        if (maxLine > 0) {
            // 计算出2行文字所能显示的长度
            availableTextWidth = (width - paddingLeft - paddingRight) * maxLine - bufferWidth;
            ellipsizeStr = (String) TextUtils.ellipsize(builder.contentString, paint, availableTextWidth - textSize, TextUtils.TruncateAt.END);
        }

        StringBuffer imgBuffer = new StringBuffer();
        for (int i = 0; i < builder.rightFlags.size(); i++) {
            imgBuffer.append(" ");
            imgBuffer.append("im" + i);
            builder.rightFlags.get(i).setTxt("im" + i);
        }

        SpannableStringBuilder ssBuilder = new SpannableStringBuilder(ellipsizeStr + imgBuffer);
//        Log.e("Tag", ellipsizeStr + "0000");

        for (FlagBean flagBean : builder.leftFlags) {
            pickFlagType(flagBean, ssBuilder);
        }
        for (FlagBean flagBean : builder.rightFlags) {
            pickFlagType(flagBean, ssBuilder);
        }
        setText(ssBuilder);
    }

    private void pickFlagType(FlagBean flagBean, SpannableStringBuilder ssBuilder) {
        int start = 0;
        int end = 0;
        if (flagBean.getType() == TagType.TYPE_FLAG) {
            start = builder.contentString.indexOf(flagBean.getTxt());
            end = start + flagBean.getTxt().length();
            if (start >= builder.contentString.length()) return;
            Log.e("Tag2",getLineSpacingExtra()+"line");
            ssBuilder.setSpan(new RadiusBackgroundSpan(flagBean.getTextColor(),
                    flagTextSize, flagBean.isFull, 10), start, end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
        } else if (flagBean.getType() == TagType.TYPE_DRAWABLE) {
            start = ssBuilder.toString().indexOf(flagBean.getTxt());
            end = start + flagBean.getTxt().length();
            Drawable drawable = flagBean.getDrawable();
            if (drawable != null) {
                drawable.setBounds(0, 0, (int) textSize, (int) textSize);
                ImageSpan imgSpan = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);
                ssBuilder.setSpan(imgSpan, start, end, SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        } else if (flagBean.getType() == TagType.TYPE_TEXT_COLOR) {
            start = ssBuilder.toString().indexOf(flagBean.getTxt());
            if (start >=0){
                end = start + flagBean.getTxt().length();
                ForegroundColorSpan colorSpan = new ForegroundColorSpan(flagBean.getTextColor() == null ?
                        textColor : flagBean.getTextColor());
                ssBuilder.setSpan(colorSpan, start, end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
            }
        }
    }

    public Builder builder() {
        builder = new Builder(this);
        return builder;
    }

    public static class Builder {

        private TagTextView view;

        private List<FlagBean> leftFlags = new ArrayList<>();
        private List<FlagBean> rightFlags = new ArrayList<>();
        private String contentString;

        public Builder(TagTextView view) {
            this.view = view;
        }

        public Builder addFlagText(String flag, int textColor, boolean isFulll, int gravity) {
            if (TextUtils.isEmpty(flag) || TextUtils.isEmpty(flag.trim())) return this;
            FlagBean flagBean = new FlagBean();
            flagBean.setTxt(flag.trim());
            flagBean.setGravity(Gravity.LEFT);
            flagBean.setTextColor(textColor);
            flagBean.setType(TagType.TYPE_FLAG);
            flagBean.isFull = isFulll;
            if (gravity == Gravity.LEFT) {
                leftFlags.add(flagBean);
            } else if (gravity == Gravity.RIGHT) {
                rightFlags.add(flagBean);
            }
            return this;
        }

        public Builder addFlagDrawable(@DrawableRes int vectorDrawableId, int gravity) {
            FlagBean flagBean = new FlagBean();
            flagBean.setGravity(gravity);
            if (view != null) {
                flagBean.setDrawable(view.getResources().getDrawable(vectorDrawableId));
            }
            flagBean.setType(TagType.TYPE_DRAWABLE);
            if (gravity == Gravity.LEFT) {
                leftFlags.add(flagBean);
            } else if (gravity == Gravity.RIGHT) {
                rightFlags.add(flagBean);
            }
            return this;
        }

        public Builder addFlagColorText(int textColor, String tex, int gravity) {
            FlagBean flagBean = new FlagBean();
            flagBean.setGravity(gravity);
            flagBean.setTxt(tex);
            flagBean.setType(TagType.TYPE_TEXT_COLOR);
            flagBean.setTextColor(textColor);
            if (gravity == Gravity.LEFT) {
                leftFlags.add(flagBean);
            } else if (gravity == Gravity.RIGHT) {
                rightFlags.add(flagBean);
            }
            return this;
        }

        public Builder setContentText(String contentString) {
            this.contentString = contentString;
            return this;
        }

        public void build() {
            if (view != null) {
                view.postInvalidate();
            }
        }
    }

    static class FlagBean {

        private int type;// 1 flag 2 drawable 3 textColor
        private int gravity;//只识别左右

        private String txt;
        private int Res;
        private Drawable drawable;
        private Bitmap bitmap;
        private Float padding;
        private Integer textColor;
        private Float textSize;
        private boolean isFull;

        public boolean isFull() {
            return isFull;
        }

        public void setFull(boolean full) {
            isFull = full;
        }


        public Float getTextSize() {
            return textSize;
        }

        public void setTextSize(Float textSize) {
            this.textSize = textSize;
        }

        public Integer getTextColor() {
            return textColor;
        }

        public void setTextColor(Integer textColor) {
            this.textColor = textColor;
        }

        public Float getPadding() {
            return padding;
        }

        public void setPadding(Float padding) {
            this.padding = padding;
        }

        public int getGravity() {
            return gravity;
        }

        public void setGravity(int gravity) {
            this.gravity = gravity;
        }

        public String getTxt() {
            return txt;
        }

        public void setTxt(String txt) {
            this.txt = txt;
        }

        public int getType() {
            return type;
        }

        public void setType(int type) {
            this.type = type;
        }

        public int getRes() {
            return Res;
        }

        public void setRes(int res) {
            Res = res;
        }

        public Drawable getDrawable() {
            return drawable;
        }

        public void setDrawable(Drawable drawable) {
            this.drawable = drawable;
        }

        public Bitmap getBitmap() {
            return bitmap;
        }

        public void setBitmap(Bitmap bitmap) {
            this.bitmap = bitmap;
        }
    }
}
